﻿using System;
using System.Net;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;
using System.Text;
using System.Collections.Specialized;
using System.Drawing.Imaging;
using System.Collections;
using System.Configuration;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Runtime.Remoting.Activation;
using System.Threading.Tasks;

namespace QD.WX.BLL
{
    /// <summary>
    /// 发送Web远程请求类
    /// </summary>
    public class WebRequestHelper
    {
        public static ICredentials Credentials = null;
        public static CookieContainer cookie = null;
        public static string Referer = "";
        public static string ContentType = "";
        public static string Host = "";
        public static string UserAgent = "";

        public static void Clear()
        {
            Credentials = null;
            cookie = null; Referer = ""; ContentType = ""; Host = ""; UserAgent = "";
        }

        public static IList<string> AgentList = new List<string>() {
            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
            "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
            "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
            "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
            "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
            "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
            "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
            "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
            "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
            "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
            "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
            "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
            "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
        };
        public WebRequestHelper()
        {
            ContentType = string.Empty;
        }
        /// <summary>
        /// 发送Get远程请求，返回UTF-8编码的响应流
        /// </summary>
        /// <param name="url">格式：http://www,03you.com/login.aspx?username=test&pwd=123</param>
        /// <param name="html"></param>
        /// <returns></returns>
        public static string Request(string url)
        {
            string html = "";
            Request(url, "", System.Text.Encoding.UTF8, out html);
            return html;
        }
        public static async Task<string> RequestAsync(string url)
        {
            
            return await RequestAsync(url, "");
           
        }
        public static string ReplaceHtml(string s)
        {
            s = s.Replace("&#39;", "'");
            s = s.Replace("&quot;", "\"");
            s = s.Replace("&amp;", "&");
            s = s.Replace("&gt;", ">");
            s = s.Replace("&lt;", "<");
            s = s.Replace("&yen;", "¥");
            s = s.Replace("amp;", "");
            s = s.Replace("&lt;", "<");
            s = s.Replace("&gt;", ">");
            s = s.Replace("&nbsp;", " ");
            s = s.Replace("\\", "");
            return s;
        }
        /// <summary>
        /// 发送POST远程请求，返回UTF-8编码的响应流
        /// </summary>
        /// <param name="url"></param>
        /// <param name="param">post请求参数,格式如：UrlEncode("参数一")=UrlEncode("值一") &UrlEncode("参数二")=UrlEncode("值二")</param>
        /// <param name="html">请求返回值</param>
        /// <returns>错误消息</returns>
        public static string Request(string url, string param, System.Text.Encoding encoding, out string html, string method = "GET")
        {
            HttpWebRequest myRequest = null;
            HttpWebResponse myResponse = null;
            Stream reqStream = null;
            StreamReader sRead = null;

            byte[] data = System.Text.Encoding.Default.GetBytes(param);
            try
            {
                //构造Web请求
                if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                    myRequest = WebRequest.Create(url) as HttpWebRequest;
                    //myRequest.ProtocolVersion = HttpVersion.Version10;
                }
                else
                    myRequest = (HttpWebRequest)WebRequest.Create(url);
                myRequest.Method = method;
                myRequest.KeepAlive = true;
                myRequest.ContentType = ContentType;
                myRequest.ContentLength = data.Length;
                myRequest.Timeout = 10000;
                myRequest.Referer = Referer;
                //myRequest.ProtocolVersion = HttpVersion.Version11;
                if (!string.IsNullOrEmpty(UserAgent))
                    myRequest.UserAgent = UserAgent;
                else
                    myRequest.UserAgent = AgentList[new Random().Next(0, AgentList.Count - 1)];
                myRequest.Headers.Add("Accept-Language", "zh-cn");
                if (cookie == null)
                    cookie = new CookieContainer();
                if (Credentials == null)
                    Credentials = CredentialCache.DefaultCredentials;
                if (!string.IsNullOrEmpty(Host))
                    myRequest.Host = Host;
                myRequest.CookieContainer = cookie;
                myRequest.KeepAlive = false;
                myRequest.ServicePoint.Expect100Continue = false;

                //请求流,发送POST参数
                if (data.Length > 0)
                {
                    reqStream = myRequest.GetRequestStream();
                    reqStream.Write(data, 0, data.Length);
                    reqStream.Close();
                }
                //响应流
                myResponse = (HttpWebResponse)myRequest.GetResponse();
                sRead = new StreamReader(myResponse.GetResponseStream(), encoding);
                html = sRead.ReadToEnd();
            }
            catch (Exception ex)
            {
                html = ex.Message;
                return ex.Message;
            }
            finally
            {
                if (sRead != null)
                    sRead.Close();

                if (reqStream != null)
                    reqStream.Close();

                if (myResponse != null)
                    myResponse.Close();

                if (myRequest != null)
                    myRequest.Abort();
            }
            return "";
        }
        public static async Task<string> RequestAsync(string url, string param, string method = "GET")
        {
            HttpWebRequest myRequest = null;
            HttpWebResponse myResponse = null;
            Stream reqStream = null;
            StreamReader sRead = null;

            byte[] data = System.Text.Encoding.Default.GetBytes(param);
            try
            {
                //构造Web请求
                if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
                {
                    ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                    myRequest = WebRequest.Create(url) as HttpWebRequest;
                    myRequest.ProtocolVersion = HttpVersion.Version10;
                }
                else
                    myRequest = (HttpWebRequest)WebRequest.Create(url);
                
                myRequest.Method = method;
                myRequest.KeepAlive = true;
                myRequest.ContentType = ContentType;
                myRequest.ContentLength = data.Length;
                myRequest.Timeout = 10000;
                myRequest.Referer = Referer;
               
                if (!string.IsNullOrEmpty(UserAgent))
                    myRequest.UserAgent = UserAgent;
                else
                    myRequest.UserAgent = AgentList[new Random().Next(0, AgentList.Count - 1)];
                myRequest.Headers.Add("Accept-Language", "zh-cn");
                if (cookie == null)
                    cookie = new CookieContainer();
                if (Credentials == null)
                    Credentials = CredentialCache.DefaultCredentials;
                if (!string.IsNullOrEmpty(Host))
                    myRequest.Host = Host;
                myRequest.CookieContainer = cookie;
                myRequest.KeepAlive = false;
                myRequest.ServicePoint.Expect100Continue = false;

                //请求流,发送POST参数
                if (data.Length > 0)
                {
                    reqStream = myRequest.GetRequestStream();
                    reqStream.Write(data, 0, data.Length);
                    reqStream.Close();
                }
                //响应流
                myResponse = (HttpWebResponse) (await myRequest.GetResponseAsync());
                sRead = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
                return sRead.ReadToEnd();
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
            finally
            {
                if (sRead != null)
                    sRead.Close();

                if (reqStream != null)
                    reqStream.Close();

                if (myResponse != null)
                    myResponse.Close();

                if (myRequest != null)
                    myRequest.Abort();
            }
        }

        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true; //总是接受 
        }

        public static void UpLoad(string url, string[] files, out string html)
        {
            html = "";
            long length = 0;
            //string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
            //string boundary ="---------------------------"+"7dd36518ec0342";

            //string boundary = "------WebKitFormBoundaryEkXHaq0izhD0XrYB";
            string boundary = "----------ei4Ef1GI3Ef1cH2ae0GI3gL6Ef1KM7";
            HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url);
            httpWebRequest2.ContentType = "multipart/form-data; boundary=" + boundary;
            httpWebRequest2.Method = "POST";
            httpWebRequest2.KeepAlive = true;
            httpWebRequest2.CookieContainer = cookie;
            httpWebRequest2.Credentials = Credentials;
            httpWebRequest2.Referer = Referer;
            Stream memStream = new System.IO.MemoryStream();
            byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
            memStream.Write(boundarybytes, 0, boundarybytes.Length);
            length += boundarybytes.Length;
            string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: image/pjpeg\r\n\r\n";
            for (int i = 0; i < files.Length; i++)
            {
                string header = string.Format(headerTemplate, "file", files[i]);
                byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
                memStream.Write(headerbytes, 0, headerbytes.Length);
                length += headerbytes.Length;
                FileStream fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read);
                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    memStream.Write(buffer, 0, bytesRead);
                    length += bytesRead;
                }
                memStream.Write(boundarybytes, 0, boundarybytes.Length);
                length += boundarybytes.Length;
                fileStream.Close();
            }
            httpWebRequest2.ContentLength = memStream.Length;
            Stream requestStream = httpWebRequest2.GetRequestStream();
            memStream.Position = 0;
            byte[] tempBuffer = new byte[memStream.Length];
            memStream.Read(tempBuffer, 0, tempBuffer.Length);
            memStream.Close();
            requestStream.Write(tempBuffer, 0, tempBuffer.Length);
            requestStream.Close();
            WebResponse webResponse2 = httpWebRequest2.GetResponse();
            Stream stream2 = webResponse2.GetResponseStream();
            StreamReader reader2 = new StreamReader(stream2);
            html = reader2.ReadToEnd();
            webResponse2.Close();
            httpWebRequest2 = null;
            webResponse2 = null;
        }

        #region 微信素材上传 旧版本 2013-10-28之前
        /*
        public static void UpLoad(string url, string[] files, out string html)
        {
            html = "";
            long length = 0;
            //string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
            //string boundary ="---------------------------"+"7dd36518ec0342";
            string boundary = "------WebKitFormBoundaryEkXHaq0izhD0XrYB";
            HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url);
            httpWebRequest2.ContentType = "multipart/form-data; boundary=" + boundary;
            httpWebRequest2.Method = "POST";
            httpWebRequest2.KeepAlive = true;
            httpWebRequest2.CookieContainer = cookie;
            httpWebRequest2.Credentials = Credentials;
            httpWebRequest2.Referer = Referer;
            Stream memStream = new System.IO.MemoryStream();
            byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
            memStream.Write(boundarybytes, 0, boundarybytes.Length);
            length += boundarybytes.Length;
            string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: image/pjpeg\r\n\r\n";
            for (int i = 0; i < files.Length; i++)
            {
                string header = string.Format(headerTemplate, "uploadfile", files[i]);
                byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
                memStream.Write(headerbytes, 0, headerbytes.Length);
                length += headerbytes.Length;
                FileStream fileStream = new FileStream(files[i], FileMode.Open, FileAccess.Read);
                byte[] buffer = new byte[1024];
                int bytesRead = 0;
                while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    memStream.Write(buffer, 0, bytesRead);
                    length += bytesRead;
                }
                memStream.Write(boundarybytes, 0, boundarybytes.Length);
                length += boundarybytes.Length;
                fileStream.Close();
            }
            httpWebRequest2.ContentLength = memStream.Length;
            Stream requestStream = httpWebRequest2.GetRequestStream();
            memStream.Position = 0;
            byte[] tempBuffer = new byte[memStream.Length];
            memStream.Read(tempBuffer, 0, tempBuffer.Length);
            memStream.Close();
            requestStream.Write(tempBuffer, 0, tempBuffer.Length);
            requestStream.Close();
            WebResponse webResponse2 = httpWebRequest2.GetResponse();
            Stream stream2 = webResponse2.GetResponseStream();
            StreamReader reader2 = new StreamReader(stream2);
            html = reader2.ReadToEnd();
            webResponse2.Close();
            httpWebRequest2 = null;
            webResponse2 = null;
        }
        */
        #endregion

        /// <summary>
        /// 下载远程图片保存到本地
        /// </summary>
        /// <param name="savedir">本地保存路径</param>
        /// <param name="imgpath">远程图片文件</param>
        /// <returns></returns>
        public static string DownRemoteImg(string savedir, string imgpath)
        {
            if (string.IsNullOrEmpty(imgpath))
                return string.Empty;
            else
            {
                string imgName = string.Empty;
                string imgExt = string.Empty;
                string saveFilePath = string.Empty;
                imgName = imgpath.Substring(imgpath.LastIndexOf("/"), imgpath.Length - imgpath.LastIndexOf("/"));
                imgExt = imgpath.Substring(imgpath.LastIndexOf("."), imgpath.Length - imgpath.LastIndexOf("."));

                saveFilePath = savedir;
                if (!Directory.Exists(saveFilePath))
                    Directory.CreateDirectory(saveFilePath);

                try
                {
                    WebRequest wreq = WebRequest.Create(imgpath);
                    wreq.Timeout = 10000;
                    HttpWebResponse wresp = (HttpWebResponse)wreq.GetResponse();
                    Stream s = wresp.GetResponseStream();
                    System.Drawing.Image img;
                    img = System.Drawing.Image.FromStream(s);
                    switch (imgExt.ToLower())
                    {
                        case ".gif":
                            img.Save(saveFilePath + imgName, ImageFormat.Gif);
                            break;
                        case ".jpg":
                        case ".jpeg":
                            img.Save(saveFilePath + imgName, ImageFormat.Jpeg);
                            break;
                        case ".png":
                            img.Save(saveFilePath + imgName, ImageFormat.Png);
                            break;
                        case ".icon":
                            img.Save(saveFilePath + imgName, ImageFormat.Icon);
                            break;
                        case ".bmp":
                            img.Save(saveFilePath + imgName, ImageFormat.Bmp);
                            break;
                    }

                    img.Dispose();
                    s.Dispose();

                    return savedir + imgName;
                }
                catch
                {
                    return "";
                }
            }
        }

    }
}